package userInterface.Panels.CommandArgumentPanels;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.*;

/**
 * {@link userInterface.panels.CommandArgumentPanels.PanelCommandArguments PanelCommandArguments} for editing
 * {@link settings.Action.Action#PAUSE Action.PAUSE} {@link settings.Command Command} arguments.
 * @author BDS
 */
public class PanelPauseArguments extends PanelCommandArguments
{
	private static final long serialVersionUID = 1L;
	
	private InputVerifier pauseInputVerifier;
	private ActionListener pauseActionListener;
	
	private GridBagLayout gblPauseArguments;
	
	private JLabel lblTime;
	private JFormattedTextField txtTime;
	
    private Border defaultBorder;
    private Border errorBorder;

	/**
	 * Class constructor.
	 */
	public PanelPauseArguments()
	{
		pauseInputVerifier = new PauseInputVerifier();
		pauseActionListener = new PauseActionListener();
		
		gblPauseArguments = new GridBagLayout();
		gblPauseArguments.columnWidths = new int[] { 100, 0 } ;
		gblPauseArguments.columnWeights = new double[] { 0.0, 1.0 };
		setLayout(gblPauseArguments);

		lblTime = new JLabel("Time (ms):");
		GridBagConstraints gbc_lblTime = new GridBagConstraints();
		gbc_lblTime.anchor = GridBagConstraints.WEST;
		gbc_lblTime.insets = new Insets(0, 0, 0, 5);
		gbc_lblTime.gridx = 0;
		gbc_lblTime.gridy = 0;
        add(lblTime, gbc_lblTime);

		txtTime = new JFormattedTextField();
		txtTime.setInputVerifier(pauseInputVerifier);
		txtTime.addActionListener(pauseActionListener);
		GridBagConstraints gbc_txtTime = new GridBagConstraints();
        gbc_txtTime.fill = GridBagConstraints.HORIZONTAL;
        gbc_txtTime.gridx = 1;
        gbc_txtTime.gridy = 0;
        add(txtTime, gbc_txtTime);
		
		defaultBorder = txtTime.getBorder();
		errorBorder = BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.RED), defaultBorder);
	}
	
    /**
     * Sets the enabled state of contained controls.
     * @param enabled Determines the enabled state of contained controls.
     */
    @Override
	public void setEnabled(boolean enabled)
	{
        super.setEnabled(enabled);
        
		lblTime.setEnabled(enabled);
		txtTime.setEnabled(enabled);
	}
	
    /**
     * Provides the external event processing class references to the contained {@link javax.swing.JComponent JComponents}.
     * @param actionListener The {@link java.awt.event.ActionListener ActionListener} for {@link javax.swing.JComboBox JComboBoxes}.
     * @param focusAdapter The {@link java.awt.event.FocusAdapter FocusAdapter} for {@link javax.swing.JFormattedTextField JFormattedTextFields}.
     * @param keyAdapter The {@link java.awt.event.KeyAdapater KeyAdapater} for {@link javax.swing.JFormattedTextField JFormattedTextFields}.
     * @param changeListener The {@link javax.swing.event.ChangeListener ChangeListener} for {@link javax.swing.JSpinner JSpinners}.
     */
    @Override
	public void addActionListeners(ActionListener actionListener, FocusAdapter focusAdapter, KeyAdapter keyAdapter, ChangeListener changeListener)
	{
		txtTime.addFocusListener(focusAdapter);
		txtTime.addKeyListener(keyAdapter);
	}
    
    /**
     * Gets the {@link settings.Action.Action#TEXTENTRY Action.TEXTENTRY} {@link settings.Command} arguments currently displayed.
     * @return The {@link settings.Action.Action#TEXTENTRY Action.TEXTENTRY} {@link settings.Command} arguments currently displayed.
     */
	@Override
	public List<String> getArguments() 
	{ 
		List<String> arguments = new ArrayList<String>();
		
		if (txtTime.getText() != null && txtTime.getText() != "")
		{
			try
			{
				arguments.add(Integer.toString(Integer.parseInt(txtTime.getText())));
			} 
			catch (Exception exception) { }
		}
		
		return arguments;
	}
	
    /**
     * <ul>
     *     <li>Sets the {@link settings.Action.Action#TEXTENTRY Action.TEXTENTRY} {@link settings.Command Command} arguments.</li>
     *     <li>Updates the UI based on the given arguments.</li>
     * </ul>
     * @param arguments The {@link settings.Action.Action#TEXTENTRY Action.TEXTENTRY} {@link settings.Command Command} arguments used to update the UI.
     */
	@Override
	public void setArguments(List<String> arguments) 
	{
		if (arguments != null && arguments.size() > 0 && arguments.get(0) != null)
		{
			txtTime.setText(arguments.get(0));
		}
		else
		{
			txtTime.setText("");
		}
	}
	
	/**
	 * {@link javax.swing.InputVerifier InputVerifier} for {@link userInterface.panels.CommandArgumentPanels.PanelPauseArguments PanelPauseArguments}
	 * {@link javax.swing.JFormattedTextField JFormattedTextFields}.
	 * @author BDS
	 */
	public class PauseInputVerifier extends InputVerifier 
	{		
		/**
		 * Determines if the provided input is valid. 
		 * Valid input is defined as being an integer greater than or equal to 0.
		 * @param component The {@link javax.swing.JFormattedTextField JFormattedTextField} to verify.
		 * @return <ul>
		 *             <li><code>true</code> if the input is valid.</li>
		 *             <li><code>false</code> if the input is invalid.</li>
		 *         </ul>
		 */
		@Override
		public boolean verify(JComponent component) 
		{
		    boolean valid = false;
		    
			if (component instanceof JFormattedTextField) 
			{
				try
				{
				    valid =  Integer.parseInt(((JFormattedTextField)component).getText()) >= 0;
				} 
				catch (Exception exception) { }
			}
			
			return valid;
		}
		
		/**
		 * <ul>
		 *     <li>Determines if the provided {@link javax.swing.JComponent JComponent} should yield focus when requested. 
		 *         Yielding focus is based on the validity of input.</li>
		 *     <li>Sets the border of the provided {@link javax.swing.JComponent JComponent} based on the validity of input.</li>
		 * </ul>
		 * @param component The {@link javax.swing.JFormattedTextField JFormattedTextField} to yield focus.
		 * @returns <ul>
		 *              <li><code>true</code> if all input is valid and focus should be yielded.</li>
		 *              <li><code>false</code> if any input is invalid and focus should not be yielded.</li>
		 *          </ul>
		 */
		@Override
		public boolean shouldYieldFocus(JComponent component) 
		{
		    boolean yieldFocus = verify(component);
		    
			if (yieldFocus)
			{
				((JFormattedTextField)component).setBorder(defaultBorder);
			}
			else
			{
				((JFormattedTextField)component).setBorder(errorBorder);
			}
			
			return yieldFocus;
		}
	}

    /**
     * {@link java.awt.event.ActionListener ActionListener} for {@link userInterface.panels.CommandArgumentPanels.PanelPauseArguments PanelPauseArguments}
     * {@link javax.swing.JFormattedTextField JFormattedTextFields}.
     * @author BDS
     */
    private class PauseActionListener implements ActionListener
    {
        /**
         * Resets focus to the {@link javax.swing.JPanel JPanel}.
         * @param actionEvent The triggering {@link java.awt.event.ActionEvent ActionEvent}.
         */
        @Override
        public void actionPerformed(ActionEvent actionEvent)
        {
            resetFocus();
        }
    }
}
